package de.farbstreich.tozen2.client;

import java.util.HashMap;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

import com.sun.corba.se.impl.javax.rmi.CORBA.Util;

import de.farbstreich.tozen2.client.GameData.Game;
import de.farbstreich.tozen2.client.GameData.Player;
import de.farbstreich.tozen2.client.board.TileEnum;
import de.farbstreich.tozen2.client.board.TozenBoard;
import de.farbstreich.tozen2.common.AePlayWave;
import de.farbstreich.tozen2.common.Tools;
import de.farbstreich.tozen2.common.TozenProtocolMessage;
import de.farbstreich.tozen2.common.TozenProtocolMessage.player;
import de.farbstreich.tozen2.common.TozenProtocolMessage.position;

public class ClientProtocolHandler {

	private GameData gameData;
	private ClientGUIFrame2 frame;

	public ClientProtocolHandler(GameData gameData) {
		this.gameData = gameData;
		this.frame = ClientGUI.frame;
	}

	/**
	 * handle protocol input
	 * 
	 * @param protocol
	 */
	public void getMethod(TozenProtocolMessage protocol) {
		switch (protocol.type) {
		case SET_NAME:
			setName(protocol);
			break;

		case GAME_TYPES:
			setGameTypes(protocol);
			break;
		case GAMES:
			setGames(protocol);
			break;
		case PLAYERS:
			setPlayers(protocol);
			break;

		case MESSAGE:
			printMessage(protocol);
			break;

		case GAME:
			setGame(protocol);
			break;
		case POSITIONS:
			setPositions(protocol);
			break;
		case CURRENT_PLAYER:
			currentPlayer(protocol);
			break;
		case END_GAME:
			(new AePlayWave("endFanfare.wav")).start();
		case SURRENDER_GAME:
			endGame(protocol);
			break;

		case PING:
			replyPing();

		default:
			missingType(protocol);
			break;
		}
		frame.currentPanel.repaint();
	}

	/**
	 * set name of local player
	 * 
	 * @protocol SET_NAME
	 * @param protocol
	 */
	private void setName(TozenProtocolMessage protocol) {
		gameData.addLocalPlayer(protocol.players.get(0).id, protocol.players
				.get(0).name);
		frame.changePanel(frame.getOverviewPanel());
	}

	/**
	 * print gameTypes list in GUI
	 * 
	 * @param protocol
	 */
	private void setGameTypes(TozenProtocolMessage protocol) {
		for (int i = 0; i < protocol.gameTypes.length; i++) {
			frame.gamesOverview.getGameTypeListComboBox().addItem(
					gameData.new GameType(protocol.gameTypes[i].id,
							protocol.gameTypes[i].title));
		}
	}

	/**
	 * print games list in GUI
	 * 
	 * @param protocol
	 */
	private void setGames(TozenProtocolMessage protocol) {
		frame.gamesOverview.getGameList().removeAll();

		if (protocol.games.length == 0) {
			return;
		}

		Vector<Game> games = new Vector<Game>();
		for (int i = 0; i < protocol.games.length; i++) {
			games.addElement(gameData.new Game(protocol.games[i].id,
					protocol.games[i].name));
		}

		frame.gamesOverview.getGameList().setListData(games);
	}

	/**
	 * set players on server and print in GUI
	 * 
	 * @param protocol
	 */
	private void setPlayers(TozenProtocolMessage protocol) {
		gameData.players = new HashMap<Integer, Player>();
		for (int i = 0; i < protocol.players.size(); i++) {
			gameData.addPlayer(protocol.players.get(i).id, protocol.players
					.get(i).name, protocol.players.get(i).color);
		}

		frame.chat.getPlayersComboBox().removeAllItems();
		frame.gamesOverview.getUserList().removeAll();

		Vector<Player> listData = new Vector<Player>();
		GameData gData = new GameData();
		frame.chat.getPlayersComboBox().addItem(gData.new Player(-2, "Alle"));
		frame.chat.getPlayersComboBox().addItem(
				gData.new Player(-1, "Mitspieler"));

		for (Player player : gameData.players.values()) {
			listData.addElement(player);
			if (player.playerId == gameData.playerId) {
				continue;
			}
			frame.chat.getPlayersComboBox().addItem(player);
		}

		frame.gamesOverview.getUserList().setListData(listData);
	}

	/**
	 * print chat message out
	 * 
	 * @param protocol
	 */
	private void printMessage(TozenProtocolMessage protocol) {
		String playerName;
		switch (protocol.players.get(0).id) {
		case -2:
			playerName = "Alle";
			break;
		case -1:
			playerName = "Mitspieler";
			break;
		case 0:
			playerName = "Server";
			break;
		default:
			playerName = gameData.players.get(protocol.players.get(0).id)
					.toString();
			break;
		}

		// BEGIN:JOKES
		if (protocol.message.equals("change my mind")
				&& protocol.players.get(0).id > 0
				&& frame.playerNameLabels != null) {
			frame.playerNameLabels[gameData.myGame.players.get(protocol.players
					.get(0).id).color].setIcon(new ImageIcon(Tools
					.getImageURL("u4_King.png")));
		} else if (protocol.message.equals("change your mind")
				&& !protocol.broadcast && frame.playerNameLabels != null
				&& protocol.players.get(0).id != gameData.playerId) {
			frame.playerNameLabels[gameData.myGame.players
					.get(gameData.playerId).color].setIcon(new ImageIcon(Tools
					.getImageURL("u4_King.png")));
		} else if (protocol.message.equals("bring me back")
				&& protocol.players.get(0).id > 0
				&& frame.playerNameLabels != null) {
			frame.playerNameLabels[gameData.myGame.players.get(protocol.players
					.get(0).id).color].setIcon(new ImageIcon(Tools
					.getImageURL("u"
							+ gameData.myGame.players.get(protocol.players
									.get(0).id).color + "_King.png")));
		} else if (protocol.message.equals("bring you back")
				&& !protocol.broadcast && frame.playerNameLabels != null) {
			frame.playerNameLabels[gameData.myGame.players
					.get(gameData.playerId).color].setIcon(new ImageIcon(
					Tools
							.getImageURL("u"
									+ gameData.myGame.players
											.get(gameData.playerId).color
									+ "_King.png")));
		} else if (protocol.message.equals("/discomode")
				&& frame.gameBoard != null) {
			frame.gameBoard.changeDiscomode(200);
		}

		// END:JOKES

		if (!protocol.broadcast) {
			playerName = playerName + " (private)";
		}
		if (!protocol.status) {
			protocol.message = "Senden der Nachricht schlug fehl: "
					+ protocol.message;
		}
		frame.chat.getMessageTextArea().append(
				playerName + ": " + protocol.message + "\n");
	}

	/**
	 * set entered game and print on GUI
	 * 
	 * @param protocol
	 */
	private void setGame(TozenProtocolMessage protocol) {

		frame.changePanel(frame.getGamePanel());

		gameData.myGame = gameData.new MyGame();

		gameData.myGame.gameId = protocol.games[0].id;
		gameData.myGame.gameTitle = protocol.games[0].title;
		gameData.myGame.gameName = protocol.games[0].name;

		frame.gameBoard.removeAllTiles();
		// frame.resetPlayerNameLabels();

		JLabel[] playerNameLabels = frame.getPlayerNameLabels();
		int i = 0;
		for (player player : protocol.games[0].players) {
			Player gamePlayer = gameData.new Player();
			gamePlayer.playerId = player.id;
			gamePlayer.name = player.name;
			gamePlayer.color = player.color;
			gameData.myGame.players.put(gamePlayer.playerId, gamePlayer);
			gameData.myGame.colors.put(gamePlayer.color, gamePlayer);

			playerNameLabels[i].setText(player.name);
			playerNameLabels[i].setEnabled(true);

			i++;
		}

		if (protocol.games[0].players.size() == 1) {
			frame.gameAction.setAdmin(true);
		}

		if (protocol.games[0].minPlayersCount <= protocol.games[0].players
				.size()) {
			frame.gameAction.enableStartButton();
		}

		// frame.currentPanel.repaint();

	}

	/**
	 * print token on GUI
	 * 
	 * @param protocol
	 */
	private void setPositions(TozenProtocolMessage protocol) {
		TozenBoard gameBoard = frame.gameBoard;
		gameBoard.removeAllTiles();

		for (position position : protocol.games[0].positions) {
			TileEnum tileId;
			switch (position.tileId) {
			case 0:
				tileId = TileEnum.TOWER;
				break;
			case 1:
				tileId = TileEnum.KNIGHT;
				break;
			case 2:
				tileId = TileEnum.ARCHER;
				break;
			default:
				System.out.println("TileType not correct set.");
				return;
			}

			if (position.x == 9 && position.y == 3 & tileId == TileEnum.TOWER)
				(new AePlayWave("quote"
						+ (int) Math.round((Math.random() * 4) % 2) + ".wav"))
						.start();

			gameBoard.addTile(position.x, position.y, gameData.myGame.players
					.get(position.playerId).color, tileId);
		}
		gameBoard.repaint();
	}

	/**
	 * set current player turn
	 * 
	 * @param protocol
	 */
	private void currentPlayer(TozenProtocolMessage protocol) {
		TozenBoard gameBoard = frame.gameBoard;

		// Startfanfaren abspielen, wenn das der SPielstart ist. Nicht aber,
		// wenn dieser SPieler der erste ist, da sich sonst Glocken und Fanfare
		// ueberdecken...
		if (gameBoard.getMovingColor() == -1
				&& gameData.playerId != protocol.players.get(0).id)
			(new AePlayWave("startFanfare.wav")).start();

		gameBoard.setMovingColor(gameData.myGame.players.get(protocol.players
				.get(0).id).color);

		if (gameData.playerId == protocol.players.get(0).id) {
			gameBoard.setMoveable(true);
		}
	}

	/**
	 * change panel to overview
	 * 
	 * @param protocol
	 */
	private void endGame(TozenProtocolMessage protocol) {
		frame.changePanel(frame.getOverviewPanel());
	}

	/**
	 * reply on incoming ping
	 */
	private void replyPing() {
		System.out.println("replyPing Function is not implemented now");
	}

	/**
	 * If an missing Type was send, print it as debug.
	 * 
	 * @param protocol
	 */
	private void missingType(TozenProtocolMessage protocol) {
		System.out.println("MissingType: " + protocol.toString());
	}

}
